<?php

namespace NorthernLights\JetBrainsLicensing\Cryptography;

use NorthernLights\JetBrainsLicensing\Exception\RsaException;
use NorthernLights\JetBrainsLicensing\PrivateKeyFile;

/**
 * Class Rsa
 * @package NorthernLights\JetBrainsLicensing\Cryptography
 */
class Rsa
{
    /** @var PrivateKeyFile */
    private $pemFile;

    /** @var resource */
    private $pemKey;

    /** @var  int */
    private $signatureAlgorithm;

    /**
     * RsaSign constructor.
     *
     * @param PrivateKeyFile $pemFile
     */
    public function __construct(PrivateKeyFile $pemFile, int $signatureAlgorithm = OPENSSL_ALGO_MD5)
    {
        $this->pemFile            = $pemFile;
        $this->pemKey             = openssl_get_privatekey((string)$this->pemFile);
        $this->signatureAlgorithm = $signatureAlgorithm;

        if (! is_resource($this->pemKey)) {
            throw new RsaException('Something gone wrong while opening file provided by ' . PrivateKeyFile::class);
        }
    }

    /**
     * Sign the contents
     *
     * @param string $contents
     *
     * @return string
     */
    public function sign(string $contents): string
    {
        openssl_sign($contents, $signature, $this->pemKey, $this->signatureAlgorithm);

        return bin2hex($signature);
    }

    /**
     * Perform integrity check of $contents against $signature
     *
     * @param string $contents
     * @param string $signature
     *
     * @return bool
     */
    public function integrityCheck(string $contents, string $signature): bool
    {
        return (bool)openssl_verify($contents, $signature, $this->pemKey, $this->signatureAlgorithm);
    }

    /**
     * Perform strict integrity check (assertion) of $contents against $signature
     *
     * @param string $contents
     * @param string $signature
     *
     * @return void
     * @throws RsaException
     */
    public function assertIntegrity(string $contents, string $signature): void
    {
        if (! $this->integrityCheck($contents, $signature)) {
            throw new RsaException('Failed asserting data integrity - signature validation failed');
        }
    }

    /**
     * Cleanup
     */
    public function __destruct()
    {
        openssl_free_key($this->pemKey);
        unset($this->pemFile);
    }
}
